﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Game.model;
using java.lang;
using java.util;
using lineage2.commons.listener;
using lineage2.commons.threading;
using org.slf4j;
using StringBuilder = java.lang.StringBuilder;

namespace Game
{
    public class GameTimeController
    {
        private class OnStartListenerImpl:OnStartListener
        {
            public OnStartListenerImpl()
		    {
			    // TODO Auto-generated constructor stub
		    }
		
		    /**
		     * Method onStart.
		     * @see lineage2.gameserver.listener.game.OnStartListener#onStart()
		     */
		    
		    public override void onStart()
		    {
			    ThreadPoolManager.getInstance().execute(_dayChangeNotify);
		    }
        }
        public class CheckSunState:RunnableImpl
        {
            public override void runImpl()
		    {
			    if (isNowNight())
			    {
				    getInstance().getListenerEngine().onNight();
			    }
			    else
			    {
				    getInstance().getListenerEngine().onDay();
			    }
			    foreach (Player player in GameObjectsStorage.getAllPlayersForIterate())
			    {
				    player.checkDayNightMessages();
				    player.sendPacket(new ClientSetTime());
			    }
		    }
        }

        public class GameTimeListenerList:ListenerList
        {
            public void onDay()
		    {
			    foreach (Listener listener in (IEnumerable)getListeners())
			    {
				    if (OnDayNightChangeListener.isInstance(listener))
				    {
					    ((OnDayNightChangeListener) listener).onDay();
				    }
			    }
		    }
		
		    /**
		     * Method onNight.
		     */
		    public void onNight()
		    {
			    foreach (Listener listener in (IEnumerable)getListeners())
			    {
				    if (OnDayNightChangeListener.isInstance(listener))
				    {
					    ((OnDayNightChangeListener) listener).onNight();
				    }
			    }
		    }
        }
        private static Logger _log = LoggerFactory.getLogger(typeof(GameTimeController));
	    /**
	     * Field TICKS_PER_SECOND. (value is 10)
	     */
	    public static int TICKS_PER_SECOND = 10;
	    /**
	     * Field MILLIS_IN_TICK.
	     */
	    public static int MILLIS_IN_TICK = 1000 / TICKS_PER_SECOND;
	    /**
	     * Field _instance.
	     */
	    private static GameTimeController _instance = new GameTimeController();
	    /**
	     * Field _gameStartTime.
	     */
	    private long _gameStartTime;
	    /**
	     * Field listenerEngine.
	     */
	    private GameTimeListenerList listenerEngine = new GameTimeListenerList();
	    /**
	     * Field _dayChangeNotify.
	     */
	    Runnable _dayChangeNotify = new CheckSunState();
        public static GameTimeController getInstance()
	    {
		    return _instance;
	    }
	
	    /**
	     * Constructor for GameTimeController.
	     */
	    private GameTimeController()
	    {
		    _gameStartTime = getDayStartTime();
		    GameServer.getInstance().addListener(new OnStartListenerImpl());
		    StringBuilder msg = new StringBuilder();
		    msg.append("GameTimeController: initialized.").append(' ');
		    msg.append("Current time is ");
		    msg.append(getGameHour()).append(':');
		    if (getGameMin() < 10)
		    {
			    msg.append('0');
		    }
		    msg.append(getGameMin());
		    msg.append(" in the ");
	        msg.append(isNowNight() ? "night" : "day");
	        msg.append('.');
		    _log.info(msg.toString());
		    long nightStart = 0;
		    long dayStart = 60 * 60 * 1000;
		    while ((_gameStartTime + nightStart) < System.currentTimeMillis())
		    {
			    nightStart += 4 * 60 * 60 * 1000;
		    }
		    while ((_gameStartTime + dayStart) < System.currentTimeMillis())
		    {
			    dayStart += 4 * 60 * 60 * 1000;
		    }
		    dayStart -= java.lang.System.currentTimeMillis() - _gameStartTime;
            nightStart -= java.lang.System.currentTimeMillis() - _gameStartTime;
		    ThreadPoolManager.getInstance().scheduleAtFixedRate(_dayChangeNotify, nightStart, 4 * 60 * 60 * 1000L);
		    ThreadPoolManager.getInstance().scheduleAtFixedRate(_dayChangeNotify, dayStart, 4 * 60 * 60 * 1000L);
	    }
        private long getDayStartTime()
        {
            Calendar dayStart = Calendar.getInstance();
            int HOUR_OF_DAY = dayStart.get(Calendar.HOUR_OF_DAY);
            dayStart.add(Calendar.HOUR_OF_DAY, -(HOUR_OF_DAY + 1) % 4);
            dayStart.set(Calendar.MINUTE, 0);
            dayStart.set(Calendar.SECOND, 0);
            dayStart.set(Calendar.MILLISECOND, 0);
            return dayStart.getTimeInMillis();
        }
        public bool isNowNight()
        {
            return getGameHour() < 6;
        }
        public int getGameTime()
        {
            return getGameTicks() / MILLIS_IN_TICK;
        }
        public int getGameHour()
        {
            return (getGameTime() / 60) % 24;
        }
        public int getGameMin()
        {
            return getGameTime() % 60;
        }
        public int getGameTicks()
	    {
		    return (int) ((java.lang.System.currentTimeMillis() - _gameStartTime) / MILLIS_IN_TICK);
	    }
	    public GameTimeListenerList getListenerEngine()
	    {
		    return listenerEngine;
	    }
        public bool addListener(GameListener listener)
	    {
		    return listenerEngine.add(listener);
	    }
	    public bool removeListener(GameListener listener)
	    {
		    return listenerEngine.remove(listener);
	    }
    }
}
